import GameFrameworkModule from "../Base/GameFrameworkModule";
import {IWebRequestManager} from "./IWebRequestManager";
import {TaskInfo} from "../Base/TaskPool/TaskInfo";
import {IWebRequestAgentHelper} from "./IWebRequestAgentHelper";
import {WebRequestTask} from "./WebRequestTask";
import {TaskPool} from "../Base/TaskPool/TaskPool";
import {WebRequestStartEventArgs} from "./WebRequestStartEventArgs";
import {WebRequestSuccessEventArgs} from "./WebRequestSuccessEventArgs";
import {WebRequestFailureEventArgs} from "./WebRequestFailureEventArgs";
import {WebRequestAgent} from "./WebRequestAgent";
import {WebRequest_Constant} from "./Constant";
import {ReferencePool} from "../Base/ReferencePool/ReferencePool";

export class WebRequestManager implements GameFrameworkModule,IWebRequestManager{
    get Timeout(): number {
        return this._Timeout;
    }
    get WorkingAgentCount(): number {
        return this._TaskPool.WorkingAgentCount;
    }
    get WaitingTaskCount(): number {
        return this._TaskPool.WaitingTaskCount;
    }
    get TotalAgentCount(): number {
        return this._TaskPool.TotalAgentCount;
    }
    get FreeAgentCount(): number {
        return this._TaskPool.FreeAgentCount;
    }
    private readonly _TaskPool:TaskPool<WebRequestTask> ;
    private _Timeout:number;
    private _WebRequestStartEventHandler:(sender,e:WebRequestStartEventArgs)=>void;
    private  _WebRequestSuccessEventHandler:(sender,e:WebRequestSuccessEventArgs)=>void;
    private  _WebRequestFailureEventHandler:(sender,e:WebRequestFailureEventArgs)=>void;
    
    
    get WebRequestFailure(){
        return this._WebRequestFailureEventHandler;
    };

    set WebRequestFailure(value){
        this._WebRequestFailureEventHandler = value;
    }
    get WebRequestStart(){
        return this._WebRequestStartEventHandler;
    }
    set WebRequestStart(value){
        this._WebRequestStartEventHandler = value;
    }
    get WebRequestSuccess(){
        return this._WebRequestSuccessEventHandler;
    }
    set WebRequestSuccess(value){
        this._WebRequestSuccessEventHandler = value;
    }

    constructor() {
        this._TaskPool = new TaskPool<WebRequestTask>();
        this._Timeout = 30;
    }

    AddWebRequest(webRequestUri: string): number;
    AddWebRequest(webRequestUri: string, postData: number[]): number;
    AddWebRequest(webRequestUri: string, userData): number;
    AddWebRequest(webRequestUri: string, postData: number[], priority: number, userData): number;
    AddWebRequest(webRequestUri: string, postData?: number[], priority?: number, userData?): number {
        if (webRequestUri == "" || webRequestUri == undefined)
        {
            throw new Error("Web request uri is invalid.");
        }

        if (this.TotalAgentCount <= 0)
        {
            throw new Error("You must add web request agent first.");
        }
        if(priority <= 0){
            priority = WebRequest_Constant.DefaultPriority;
        }
        let webRequestTask:WebRequestTask = WebRequestTask.Create(webRequestUri, postData, priority, this._Timeout, userData);
        this._TaskPool.AddTask(webRequestTask);
        return webRequestTask.serialId;
    }

    AddWebRequestAgentHelper(webRequestAgentHelper: IWebRequestAgentHelper): void {
        let agent:WebRequestAgent = new WebRequestAgent(webRequestAgentHelper);
        agent.WebRequestAgentStart = this.OnWebRequestAgentStart;
        agent.WebRequestAgentSuccess = this.OnWebRequestAgentSuccess;
        agent.WebRequestAgentFailure = this.OnWebRequestAgentFailure;
        this._TaskPool.AddAgent(agent);
    }

    private OnWebRequestAgentFailure(e:WebRequestAgent,error:string) {
        if (this._WebRequestFailureEventHandler != null)
        {
            let webRequestFailureEventArgs:WebRequestFailureEventArgs = WebRequestFailureEventArgs.Create(e.Task().serialId, e.Task().webrequesturi, error, e.Task().userdata);
            this._WebRequestFailureEventHandler(this, webRequestFailureEventArgs);
            ReferencePool.Release(webRequestFailureEventArgs);
        }
    }

    private OnWebRequestAgentSuccess(e:WebRequestAgent,data:number[]) {
        if (this._WebRequestSuccessEventHandler != null)
        {
            let webRequestSuccessEventArgs:WebRequestSuccessEventArgs = WebRequestSuccessEventArgs.Create(e.Task().serialId, e.Task().webrequesturi, data, e.Task().userdata);
            this._WebRequestSuccessEventHandler(this, webRequestSuccessEventArgs);
            ReferencePool.Release(webRequestSuccessEventArgs);
        }
    }

    private OnWebRequestAgentStart(e:WebRequestAgent) {
        if (this._WebRequestStartEventHandler != null)
        {
            let webRequestStartEventArgs:WebRequestStartEventArgs = WebRequestStartEventArgs.Create(e.Task().serialId, e.Task().webrequesturi, e.Task().userdata);
            this._WebRequestStartEventHandler(this, webRequestStartEventArgs);
            ReferencePool.Release(webRequestStartEventArgs);
        }
    }

    GetAllWebRequestInfos(): TaskInfo[] {
        return this._TaskPool.GetAllTaskInfos();
    }

    get Priority(): number {
        return 0;
    }

    RemoveAllWebRequests(): void {
        this._TaskPool.RemoveAllTasks();
    }

    RemoveWebRequest(serialId: number): boolean {
        return this._TaskPool.RemoveTask(serialId);
    }

    Shutdown(): void {
        this._TaskPool.Shutdown();
    }

    Update(elapseSeconds: number, realElapseSeconds: number): void {
        this._TaskPool.Update(elapseSeconds, realElapseSeconds);
    }

    get baseName(): string {
        return "GameFrameworkModule";
    }

}